
import { createConnection, Connection, ConnectionOptions } from "typeorm";
import { SIP_Server_Options, SIP_Server, stringify, SIP_Message, SIP_Remote } from "@yjkhtddx/sip.ts";
import { User } from "./entity/User";
import { EventEmitter } from "events";


interface SIP_Session {
    id: string;
    realm: string;
    access_type: string;
    password: string;
    expiress_time: Date;
}

interface GBServiceData {
    message: SIP_Message,
    remote: SIP_Remote,
    stream?: Buffer
}


interface GBServiceEventEmitterEventMap {
    "data": GBServiceData;
}

class GBServiceEventEmitter extends EventEmitter {

    private addEventListener<K extends keyof GBServiceEventEmitterEventMap>(type: K, listener: (this: GBServiceEventEmitter, ev: GBServiceEventEmitterEventMap[K]) => any): void{

    };
    private removeEventListener<K extends keyof GBServiceEventEmitterEventMap>(type: K, listener: (this: GBServiceEventEmitter, ev: GBServiceEventEmitterEventMap[K]) => any): void{
        
    };
}


export class GBService extends EventEmitter {

    private connectionDB?: Connection = undefined;
    private GBService?: SIP_Server = undefined;
    private SIP_SERVER_IP: string = '0.0.0.0';
    private SIP_SERVER_PORT: number = 15060;
    private SIP_SERVER_SERIAL: string = '41010200002000000002';
    private SIP_SERVER_DOMAIN: string = '4101020000';
    private SIP_SERVER_DEBUG: boolean = false;
    private SIP_SERVER_REALM: string = 'DerekLiu';
    private SIP_SERVER_SESSION_EXPIRESS: string;
    private SIP_SERVER_URI: string = `sip:${this.SIP_SERVER_SERIAL}@${this.SIP_SERVER_IP}:${this.SIP_SERVER_PORT}`;

    constructor(
    ) {
        super();
        if (GBService.instance !== undefined) throw new Error("SIP can't constructor again");
        GBService.instance = this;
        GBService.instance.startSIP();
    }

    // private session: Map<string, SIP_Session> = new Map();//TODO 可改为数据库
    private static instance?: GBService = undefined; //单利对象
    // public static get Instance(): GBService {
    //     if (GBService.instance === undefined) {
    //         GBService.instance = new GBService();
    //     }message: SIP_Message, remote: SIP_Remote, stream?: Buffer
    private async startSIP(): Promise<void> {
        await this.createConnection();
        await this.cretaeGBService();
    }

    private static printfSipMessage(message: SIP_Message, title: string): void {
        console.log("===================================================================");
        console.log(title);
        console.log("===================================================================");
        console.log(stringify(message));
        console.log("===================================================================");
    };

    private async createConnection(): Promise<void> {
        const options: ConnectionOptions = {
            type: 'sqlite',
            database: 'database.sqlite',
            synchronize: true,
            logging: false,
            entities: [
                "src/entity/**/*.ts"
            ],
        };
        await createConnection(options).then(async connection => {
            this.connectionDB = connection;
            // console.log(`${options.database} connection succeed`);

            console.log("Inserting a new user into the database...");
            const user = new User();
            user.firstName = "Timber2";
            user.lastName = "Saw2";
            user.age = 25;
            await this.connectionDB.manager.save(user);
            console.log("Saved a new user with id: " + user.id);
            console.log("Loading users from the database...");
            const users = await this.connectionDB.manager.find(User);
            console.log("Loaded users: ", users);
            console.log("Here you can setup and run express/koa/any other framework.");

        }).catch(error => console.log(error));
    }

    private async cretaeGBService(): Promise<void> {
        const options: SIP_Server_Options = {
            "port": 15061
        };
        const server = new SIP_Server(options);
        server.addListener('data', async (message: SIP_Message, remote: SIP_Remote, stream?: Buffer) => {
            GBService.printfSipMessage(message, "onMessage");
        });
        console.log(`SIP server start listen port:${options.port}`);
    }
}